10298. Степень строки
Обозначим через a * b
конкатенацию строк a и b. Например, если a = "abc" и b = "def", то a * b = "abcdef". Если считать конкатенацию строк умножением, то можно
определить операцию возведения в степень следующим образом:
a0 = “” (пустая строка)
an+1 = a * an
По заданной строке s необходимо найти наибольшее значение n, для которого s = an для
некоторой строки a.
Вход. Каждый
тест состоит из одной строки s,
содержащей печатные символы. Строка s
содержит не менее одного и не более миллиона символов. Последний тест содержит
точку и не обрабатывается.
Выход. Для каждой входной строки s вывести наибольшее значение n, для которого s = an для
некоторой строки a.
abcd
aaaa
ababab
.
Пример выхода
1
4
3
строки – префикс-функция
Рассмотрим слово S длиной len, являющееся повторением слова X n
раз. То есть S = Xn. Пусть
длина слова X равна k, причем оно само не является
повторением никакого слова.
Построим префикс-функцию p слова
S. Поскольку индексы строки начинаются с нуля, то подстрока S[k ...2k – 1] является копией S[0 ...k
– 1] и соответственно p[k] = 1, p[k + 1] = 2, …, p[2k – 1] = k. Третий повтор
слова X находится в позициях S[2k ...3k – 1] и при этом p[2k] =
k + 1, p[2k + 1] = k + 2, …, p[3k – 1] = 2k. Последняя ячейка префикс-функции p[nk – 1] равна (n – 1)k.
Вычислим разницу: len – p[len – 1] = nk – (n – 1)k = k, что равно длине
слова X. Тогда степень n слова S равна len / k. При этом если len не делится на k, то S не является повторением никакого слова и следует
положить n = 1.
В векторе p строим префикс-функцию строки s.
vector<int> p;
char s[1000001];
Функция MaxBorderArray строит префикс-функцию строки s.
vector<int> MaxBorderArray(char
*s)
{
int i, j;
vector<int>
p(len,0);
p[0] = 0;
for(i = 1; i
< len; i++)
{
j = p[i - 1];
while ((j
> 0) && (s[i] != s[j])) j = p[j - 1];
if (s[i] ==
s[j]) p[i] = j + 1; else p[i] = 0;
}
return p;
}
Основная часть программы. Читаем входную строку s, вычисляем ее длину len. Вычисляем в массиве p
префикс-функцию.
while (gets(s) && strcmp(s,"."))
{
len = strlen(s);
p = MaxBorderArray(s);
Вычисляем разницу между длиной слова и длиной самого
длинного префикса строки s,
совпадающей с ее суффиксом.
k = len - p[len-1];
Если длина слова len
не делится на полученную разницу res,
то входная строка s не является
степенью никакой строки. Иначе степень строки s равна len / res.
if (len % k)
n = 1; else n = len / k;
printf("%d\n",n);
}